package com.jprocms.module.cms.service.imgblock;

import cn.hutool.core.date.DateUtil;
import com.jpro.framework.common.util.date.DateUtils;
import com.jpro.framework.tenant.core.context.TenantContextHolder;
import com.jprocms.module.cms.dal.dataobject.content.ContentDO;
import com.jprocms.module.cms.dto.JobDto;
import com.jprocms.module.cms.enums.EnumImgblockActivePos;
import com.jprocms.module.cms.enums.EnumJobStatus;
import com.jprocms.module.cms.enums.EnumJobType;
import com.jprocms.module.cms.framework.job.util.XxlJobUtil;
import com.jprocms.module.cms.service.channel.ChannelService;
import com.jprocms.module.cms.service.job.JobService;
import com.jprocms.module.cms.service.site.SiteService;
import com.jprocms.module.cms.service.staticpage.StaticHtmlService;
import com.jprocms.module.cms.util.CronUtil;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import com.jprocms.module.cms.controller.admin.imgblock.vo.*;
import com.jprocms.module.cms.dal.dataobject.imgblock.ImgblockDO;
import com.jpro.framework.common.pojo.PageResult;
import com.jpro.framework.common.pojo.PageParam;
import com.jpro.framework.common.util.object.BeanUtils;

import com.jprocms.module.cms.dal.mysql.imgblock.ImgblockMapper;

import static com.jpro.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.jprocms.module.cms.constant.CmsSysConstants.DEF_TOP_LEVEL;
import static com.jprocms.module.cms.constant.JobConstant.*;
import static com.jprocms.module.cms.constant.JobConstant.JOB_HANDLER_CONTENT_OFFLINE;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.*;

/**
 * 飘窗板块 Service 实现类
 *
 * @author jprocms
 */
@Slf4j
@Service
@Validated
public class ImgblockServiceImpl implements ImgblockService {

    @Resource
    private ImgblockMapper imgblockMapper;
    @Resource
    private StaticHtmlService staticHtmlService;
    @Resource
    private SiteService siteService;
    @Resource
    private ChannelService channelService;
    @Resource
    private JobService jobService;

    @Override
    public Long createImgblock(ImgblockSaveReqVO createReqVO) {
        // 插入
        ImgblockDO imgblock = BeanUtils.toBean(createReqVO, ImgblockDO.class);
        imgblockMapper.insert(imgblock);
        createScheduleTask(imgblock);
        // 返回
        return imgblock.getId();
    }

    @Override
    public void updateImgblock(ImgblockSaveReqVO updateReqVO) {
        // 校验存在
        ImgblockDO oldImgBlockDO = validateImgblockExists(updateReqVO.getId());
        // 更新
        ImgblockDO updateObj = BeanUtils.toBean(updateReqVO, ImgblockDO.class);
        imgblockMapper.updateById(updateObj);
        createScheduleTask(updateObj);
        staticHtmlPage(oldImgBlockDO,updateObj);
    }

    @Override
    public void deleteImgblock(Long id) {
        // 校验存在
        ImgblockDO imgBlockDO =validateImgblockExists(id);
        // 删除
        imgblockMapper.deleteById(id);
        staticHtmlPage(null,imgBlockDO);
    }

    private ImgblockDO validateImgblockExists(Long id) {
        final ImgblockDO imgblockDO = imgblockMapper.selectById(id);
        if (imgblockDO == null) {
            throw exception(IMGBLOCK_NOT_EXISTS);
        }
        return imgblockDO;
    }

    @Override
    public ImgblockDO getImgblock(Long id) {
        return imgblockMapper.findById(id);
    }

    @Override
    public PageResult<ImgblockDO> getImgblockPage(ImgblockPageReqVO pageReqVO) {
        return imgblockMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ImgblockDO> getImgblockList(ImgblockPageReqVO pageReqVO) {
        return imgblockMapper.selectList(pageReqVO);
    }

    public void staticHtmlPage(ImgblockDO oldImgblockDO, ImgblockDO imgblockDO){
        //生效位置发生变化，老的也需要重新静态化
        if(oldImgblockDO!=null&&imgblockDO!=null&&(!oldImgblockDO.getActivePos().equals(imgblockDO.getActivePos())
                ||(EnumImgblockActivePos.CHANNEL.getPos().equals(imgblockDO.getActivePos())&&!imgblockDO.getActiveChannelId().equals(oldImgblockDO.getActiveChannelId()))
        )){
            doStaticHtmlPage(oldImgblockDO);
        }
        //新的静态化
        doStaticHtmlPage(imgblockDO);
    }

    private void doStaticHtmlPage(ImgblockDO imgblockDO){
        if(EnumImgblockActivePos.INDEX.getPos().equals(imgblockDO.getActivePos())){
            staticHtmlService.updateIndexHtml(siteService.getSite(imgblockDO.getSiteId()));
        }else{
            staticHtmlService.updateChannelHtml(channelService.getChannel(imgblockDO.getActiveChannelId()));
        }
    }

    public void createScheduleTask(ImgblockDO imgblockDO) {
        final LocalDateTime activetimeBegin = imgblockDO.getActivetimeBegin();
        final LocalDateTime activetimeEnd = imgblockDO.getActivetimeEnd();
        final LocalDateTime now = LocalDateTime.now();
        if (activetimeBegin != null && activetimeBegin.isAfter(now)) {
            JobDto job = new JobDto();
            job.setJobName(String.format("飘窗生效开始%s,ID:%s", imgblockDO.getName(), imgblockDO.getId()));
            job.setJobType(EnumJobType.IMGBLOCK_ACTIVE_BEGIN.getCode());
            job.setDataId(imgblockDO.getId());
            job.setStatus(EnumJobStatus.RUNABLE.getCode());
            job.setParams(imgblockDO.getId().toString());
            job.setCron(CronUtil.date2Cron(DateUtils.of(activetimeBegin), CronUtil.CRON_DATE));
            job.setJobHandler(JOB_HANDLER_IMGBLOCK_ACTIVE_BEGIN);
            jobService.addOrUpdateJob(job);
        }
        if (activetimeEnd != null) {
            JobDto job = new JobDto();
            job.setJobName(String.format("飘窗生效结束%s,ID:%s", imgblockDO.getName(), imgblockDO.getId()));
            job.setJobType(EnumJobType.IMGBLOCK_ACTIVE_END.getCode());
            job.setDataId(imgblockDO.getId());
            job.setStatus(EnumJobStatus.RUNABLE.getCode());
            job.setParams(imgblockDO.getId().toString());
            job.setCron(CronUtil.date2Cron(DateUtils.of(activetimeEnd), CronUtil.CRON_DATE));
            job.setJobHandler(JOB_HANDLER_IMGBLOCK_ACTIVE_END);
            jobService.addOrUpdateJob(job);
        }
    }

    @XxlJob(JOB_HANDLER_IMGBLOCK_ACTIVE_BEGIN)
    public void activeBeginJob() {
        String param = XxlJobUtil.getBussinessParam();
        log.info("创建飘窗生效开始任务，参数：{}", param);
        if (!StringUtils.isNumeric(param)) {
            log.error("飘窗生效开始：{} 错误，定时任务执行失败", param);
            return;
        }
        Long id = Long.valueOf(param);
        //定时任务这里查询数据忽略租户条件
        TenantContextHolder.setIgnore(true);
        final ImgblockDO imgblock = getImgblock(id);
        if (imgblock == null) {
            log.error("id为：{}不存在，定时任务执行失败", id);
            return;
        }
        doStaticHtmlPage(imgblock);
        //执行完成后删除
        jobService.deleteByJobTypeAndDataId(EnumJobType.IMGBLOCK_ACTIVE_BEGIN.getCode(), id);
    }

    @XxlJob(JOB_HANDLER_IMGBLOCK_ACTIVE_END)
    public void activeEndJob() {
        String param = XxlJobUtil.getBussinessParam();
        log.info("创建飘窗生效结束任务，参数：{}", param);
        if (!StringUtils.isNumeric(param)) {
            log.error("飘窗生效结束：{} 错误，定时任务执行失败", param);
            return;
        }
        Long id = Long.valueOf(param);
        //定时任务这里查询数据忽略租户条件
        TenantContextHolder.setIgnore(true);
        final ImgblockDO imgblock = getImgblock(id);
        if (imgblock == null) {
            log.error("id为：{}不存在，定时任务执行失败", id);
            return;
        }
        doStaticHtmlPage(imgblock);
        //执行完成后删除
        jobService.deleteByJobTypeAndDataId(EnumJobType.IMGBLOCK_ACTIVE_END.getCode(), id);
    }

}